package com.mytx.notify.controller;

import com.mytx.common.constant.Constant;
import com.mytx.common.pojo.CommonResult;
import com.mytx.common.utils.Utils;
import com.mytx.mapper.UserMapper;
import com.mytx.notify.service.MobileCodeService;
import com.mytx.notify.service.NotifyService;
import com.mytx.pojo.User;
import com.mytx.pojo.UserExample;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


@SuppressWarnings({"Duplicates", "SpringJavaInjectionPointsAutowiringInspection"})
@RefreshScope
@RestController
public class NotifyController implements NotifyService {

    private static final Logger logger = LoggerFactory.getLogger(NotifyController.class);


    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private MobileCodeService mobileCodeService;


    //手机验证码过期时间： 分钟
    @Value("${redisKey.mobile_code_expire}")
    private Long mobileCodeExpire;

    @Value("${phone_number_match}")
    String phoneNumberMatch;
    /*
     某手机号发送验证码次数记录的过期时间，例：限时30分钟只能发3条，
     从发送第一条开始记录时间，每次发送，更新发送条数，
     当前时间段可发送次数用完，得等这个手机号对应的次数记录过期自动删除后，才能重新发送
     单位：分钟
     */
    @Value("${redisKey.send_count_expire}")
    private Long sendCountExpire;
    //一段时间内，发送条数
    @Value("${mobile_number_ceiling}")
    private Integer mobileNumberCeiling;

    /**
     * 这个方法用于注册发送短信，会检查手机号码是否已经被使用，如果号码已经被使用，则返回错误
     *
     * @return
     * @throws Exception
     */
    @Override
    public CommonResult sendMobileCode(@RequestBody String phoneNumber) {
        logger.info("sendMobileCode:" + phoneNumber);

        // 检测手机号格式
        if (!isPhoneNumber(phoneNumber)) {

            return CommonResult.build(Constant.PHONE_NUMBER_FORMAT_ERROR, "手机格式错误");
        }

        UserExample example = new UserExample();
        UserExample.Criteria criteria = example.createCriteria();
        criteria.andPhoneEqualTo(phoneNumber);
        List<User> tbUsers = userMapper.selectByExample(example);

        if (tbUsers != null && tbUsers.size() != 0) {
            return CommonResult.build(Constant.SEND_MOBILE_CODE_FAIL_ENGAGED, "该号码已经被注册");
        }
        //手机号没有被注册
        return mobileNotify(phoneNumber);


    }

    /**
     * 这个方法用于通过电话号码重置密码，会检查手机号码是否已经被使用，如果号码没有被使用，则返回错误
     *
     * @return
     * @throws Exception
     */

    @PostMapping("/sendMobileCode_1")
    public CommonResult sendMobileCode_1(@RequestBody String phoneNumber) {
        logger.info("sendMobileCode_1:" + phoneNumber);
        // 检测手机号格式
        if (!isPhoneNumber(phoneNumber)) {

            return CommonResult.build(Constant.PHONE_NUMBER_FORMAT_ERROR, "手机格式错误");
        }

        UserExample example = new UserExample();
        UserExample.Criteria criteria = example.createCriteria();
        criteria.andPhoneEqualTo(phoneNumber);
        List<User> tbUsers = userMapper.selectByExample(example);

        if (tbUsers != null && tbUsers.size() != 0) {
            //手机号没有被注册
            return mobileNotify(phoneNumber);
        }
        return CommonResult.build(Constant.PHONE_NUMBER_INVALID, "该号码尚未绑定任何账户");

    }

    /**
     * 发送短信
     *
     * @param phone 手机号码 带国际区号
     * @return ({ ' rs ' : 1 })   第一次
     * ({'remain':'该手机还可获取2次验证码，请尽快完成验证'})
     * 第二次提示
     * ({'remain':'该手机还可获取1次验证码，请尽快完成验证'})
     * 第三次提示
     * ({"rs":1})   第四次
     * ({"rs":-1})  网络繁忙
     */
    @Override

    public CommonResult mobileNotify(@PathVariable("mobile") String phone) {
        //随机生成发送给客户端的手机验证码
        int code = (int) ((Math.random() * 9 + 1) * 100000);

        //查询Redis  号码1小时获取次数

        String sendCountKey = Constant.SEND_COUNT + phone;
        String mobileCodeKey = Constant.MOBILE_CODE + phone;
        String sendCount = redisTemplate.opsForValue().get(sendCountKey);

        //查询不到
        if (StringUtils.isBlank(sendCount)) {

            // 发送短信==================
            //  String result = mobileCodeService.sendRegisterMobileCode(mobile, code + "", null);
            //初始化该号码发短信记录到Redis并设置过期时间
            redisTemplate.opsForValue().set(sendCountKey, 1 + "", sendCountExpire, TimeUnit.MINUTES);

            //保存短信验证码code到Redis
            redisTemplate.opsForValue().set(mobileCodeKey, code + "", mobileCodeExpire, TimeUnit.MINUTES);
            return CommonResult.ok(1);
        }

        //判断当前手机号发送短信次数是否超过限制
        int nub = Integer.parseInt(sendCount);
        if (nub >= mobileNumberCeiling) {
            return new CommonResult(Constant.SEND_MOBILE_CODE_FAIL_HAVE_NO_COUNT, "当前手机号发送短信次数超过限制", redisTemplate.getExpire(sendCountKey, TimeUnit.MINUTES));
        }

        // 发送短信==================
        //   String result = mobileCodeService.sendRegisterMobileCode(mobile, code + "", null);

        //把发短信次数增加 1
        Long increment = redisTemplate.opsForValue().increment(sendCountKey, 1);

        //保存code到Redis
        redisTemplate.opsForValue().set(mobileCodeKey, code + "", mobileCodeExpire, TimeUnit.MINUTES);
        return CommonResult.ok(increment);

    }

    private boolean isPhoneNumber(String mobiles) {

        Pattern p = Pattern.compile(phoneNumberMatch);
        Matcher m = p.matcher(mobiles);
        return m.matches();
    }


}
